package com.jwsoft.manager.core.integration.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bifang.assistant.common.vo.BaseVO;
import com.bifang.assistant.common.vo.SessionInfo;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.cache.redis.RedisHelper;
import com.bifang.engine.data.core.util.PagerUtil;
import com.bifang.module.base.common.vo.common.CommonVO;
import com.bifang.module.base.common.vo.excel.ExcelModelVO;
import com.bifang.module.base.common.vo.excel.ExcelVO;
import com.bifang.module.base.core.helper.DictHelper;
import com.bifang.module.base.core.helper.ExcelCommonHelper;
import com.bifang.module.base.core.integration.CommonIntegration;
import com.bifang.module.system.core.dao.model.SysDict;
import com.bifang.module.system.core.dao.service.SysDictService;
import com.bifang.module.system.core.integration.impl.ExcelIntegrationImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.constant.EduCache;
import com.jwsoft.manager.common.enums.EduAddressDictEnum;
import com.jwsoft.manager.common.enums.HandleStatusEnum;
import com.jwsoft.manager.common.vo.eduAddress.*;
import com.jwsoft.manager.common.vo.eduAddressTree.AddressRequest;
import com.jwsoft.manager.common.vo.eduAddressTree.AddressVO;
import com.jwsoft.manager.common.vo.eduAddressTreeInitial.EduAddressTreeInitialQueryVO;
import com.jwsoft.manager.common.vo.eduSchool.EduSchoolVO;
import com.jwsoft.manager.core.dao.model.*;
import com.jwsoft.manager.core.dao.service.*;
import com.jwsoft.manager.core.integration.EduAddressIntegration;
import com.jwsoft.manager.core.integration.addressParse.SmartParse;
import com.jwsoft.manager.core.integration.eduAddressTree.EduAddressTreeIntegration;
import com.jwsoft.manager.core.task.address.AddressObserver;
import com.jwsoft.manager.core.util.AddressUtil;
import com.jwsoft.manager.core.util.EduHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 地址表业务实现类
 *
 * @author wangtao
 * @since 2022-11-24
 */
@ApiService(funcCode = "eduaddress", title = "地址表")
@Slf4j
public class EduAddressIntegrationImpl implements EduAddressIntegration {



    private static final List<AddressObserver> OBSERVER_LIST = new ArrayList<>();

    @Autowired
    public EduAddressService eduAddressService;

    @Autowired
    private EduHelper eduHelper;

    @Autowired
    private EduSchoolService schoolService;

    @Autowired
    public EduAddressSchoolService eduAddressSchoolService;
    @Autowired
    private EduAddressTreeService eduAddressTreeService;

    @Autowired
    private EduHouseDetailService eduHouseDetailService;

    @Autowired
    private EduHouseService eduHouseService;

    @Autowired
    public ExcelIntegrationImpl excelIntegration;
    @Autowired
    EduAddressTreeIntegration eduAddressTreeIntegration;

    @Autowired
    EduAddressTreeOriginalService originalService;

    @Autowired
    private DictHelper dictHelper;

    @Autowired
    SysDictService sysDictService;

    @Value("${spring.servlet.multipart.location}")
    private String tempPath;

    @Autowired
    ExcelCommonHelper excelCommonHelper;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Autowired
    private RedisHelper redisHelper;

    @Autowired
    private CommonIntegration commonIntegration;

    @PostConstruct
    private void init() {
        //初始化OBSERVER_LIST
        log.info("初始化观察者");
        String[] beanNames = applicationContext.getBeanNamesForType(AddressObserver.class);
        for (String beanName : beanNames) {
            OBSERVER_LIST.add((AddressObserver) applicationContext.getBean(beanName));
        }
    }

    @Override
    @OpApi(funcCode = "eduaddress0001", title = "地址表分页查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduAddressVO> getList(EduAddressQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        if(!ObjectUtils.isEmpty(vo.getAddressName())){
            String addressName = Convert.toDBC(vo.getAddressName());
            vo.setAddressName(addressName);
        }
        if (ObjectUtils.isEmpty(vo.getStreetCodeFlag())){
            vo.setStreetCodeFlag(false);
        }
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        LambdaQueryWrapper<EduAddress> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(!ObjectUtils.isEmpty(vo.getHandleStatus()), EduAddress::getHandleStatus, vo.getHandleStatus());
        queryWrapper.like(!ObjectUtils.isEmpty(vo.getAddressName()), EduAddress::getAddressName, vo.getAddressName());
        queryWrapper.eq(!ObjectUtils.isEmpty(vo.getYear()), EduAddress::getYear, vo.getYear());
        queryWrapper.eq(!ObjectUtils.isEmpty(vo.getFictitious()), EduAddress::getFictitious, vo.getFictitious());
        queryWrapper.eq(!ObjectUtils.isEmpty(vo.getAddressId()), EduAddress::getAddressId, vo.getAddressId());
        queryWrapper.orderByDesc(EduAddress::getHandleTime,EduAddress::getUpdateTime,EduAddress::getAddressName);
        if (vo.getStreetCodeFlag()){
            queryWrapper.isNull(EduAddress::getStreetCode);
        }
        List<EduAddress> list = eduAddressService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduAddress> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduAddressVO> resultList = Convert.toList(EduAddressVO.class, pageInfo.getList());
        resultList.stream().map(item ->{
            if (!ObjectUtils.isEmpty(item.getStreetCode())){
                String key = EduCache.EDU_ADDRESS_STREET_CODE+item.getStreetCode();
                if (redisHelper.hasKey(key)){
                    String streetCodeName = (String) redisHelper.get(key);
                    item.setStreetCodeName(streetCodeName);
                    return item;
                }
                QueryWrapper<EduAddressTreeOriginal> wrapper = new QueryWrapper<>();
                wrapper.lambda().select(EduAddressTreeOriginal::getAreaName).eq(EduAddressTreeOriginal::getAreaCode,item.getStreetCode());
                EduAddressTreeOriginal original = originalService.getOne(wrapper, false);
                if (original != null){
                    redisHelper.set(key,original.getAreaName(),86400);
                    item.setStreetCodeName(original.getAreaName());
                }
            }
            return item;
        }).collect(Collectors.toList());
        // 转义数据字典值
        dictHelper.valueToName(resultList, Arrays.asList(EduAddressDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduaddress0002", title = "地址表根据主键查询详情", funcType = FuncTypeEnum.query)
    public EduAddressVO getById(EduAddressKeyVO vo) {
        EduAddress entity = eduAddressService.getById(vo.getAddressId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduAddressVO result = Convert.convert(EduAddressVO.class, entity);
        return result;
    }

    /**
     * 保存前统一校验
     */
    @Override
    @OpApi(funcCode = "eduaddress0003", title = "地址表保存前校验", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduAddressVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "eduaddress0004", title = "地址表新增", funcType = FuncTypeEnum.insert)
    @Transactional
    public EduAddressVO add(EduAddressVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduAddress entity = Convert.convert(EduAddress.class, vo);
        eduAddressService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setAddressId(entity.getAddressId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduaddress0005", title = "地址表修改", funcType = FuncTypeEnum.update)
    @Transactional
    public EduAddressVO edit(EduAddressVO vo) {
        if (ObjectUtils.isEmpty(vo.getAddressId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduAddress oldEntity = eduAddressService.getById(vo.getAddressId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduAddress entity = Convert.convert(EduAddress.class, vo);
        eduAddressService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduaddress0006", title = "地址表根据主键删除", funcType = FuncTypeEnum.delete)
    @Transactional
    public void del(EduAddressKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getAddressId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduAddress entity = eduAddressService.getById(vo.getAddressId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduAddressService.removeById(vo.getAddressId());
    }


    @Override
    @OpApi(funcCode = "eduaddress0007", title = "地址管理查询数据(包括父地址名称)", funcType = FuncTypeEnum.query)
    public PageInfo<EduAddressVO> getParentAdderssList(SchoolAddressQueryVO vo) {
        String realProperty = vo.getRealProperty();
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        if(StringUtils.isNotBlank(vo.getAddressName())){
            vo.setAddressName(Convert.toDBC(vo.getAddressName()));
        }
        // 不动产权号查询地址id
        if (StringUtils.isNotBlank(realProperty)) {
            QueryWrapper<EduHouseDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(EduHouseDetail::getRealProperty, realProperty);
            List<EduHouseDetail> houseDetailList = eduHouseDetailService.list(queryWrapper);
            List<String> houseIdList = houseDetailList.stream().map(EduHouseDetail::getHouseId).distinct().collect(Collectors.toList());
            List<EduHouse> eduHouses = eduHouseService.listByIds(houseIdList);
            List<String> addressIdList = eduHouses.stream().map(EduHouse::getAddressId).distinct().collect(Collectors.toList());
            if (CollectionUtils.isEmpty(addressIdList)) {
                // 判断是否为空，为空则返回空参数
                return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
            }
            vo.setAddressIdList(addressIdList);
        }
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());

        if (StringUtils.isNotBlank(vo.getAddressName())){
         vo.setAddressName( Convert.toDBC(vo.getAddressName()));
        }

        List<EduAddressVO> list = eduAddressSchoolService.getAddressNo(vo);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduAddressVO> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduAddressVO> resultList = Convert.toList(EduAddressVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduaddress0008", title = "取消关联学校", funcType = FuncTypeEnum.delete)
    @Transactional
    public void delAddressSchoolData(EduAddressVO vo) {
        String addressId = vo.getAddressId();
        Assert.hasText(addressId, "地址id不能为空");
        EduAddress address = eduAddressService.getById(addressId);
        Assert.notNull(address, "查询不到地址信息");
        QueryWrapper<EduAddressSchool> addressSchoolQueryWrapper = new QueryWrapper<>();
        addressSchoolQueryWrapper
                .lambda()
                .eq(EduAddressSchool::getAddressId, addressId)
                .eq(
                        !ObjectUtils.isEmpty(vo.getSchoolName()),
                        EduAddressSchool::getSchoolName,
                        vo.getSchoolName());
        List<EduAddressSchool> addressSchoolList =
                eduAddressSchoolService.list(addressSchoolQueryWrapper);
        if (addressSchoolList.size() <= 0) {
            throw new AppException("未查询到关联学校");
        } else {
            eduAddressSchoolService.removeByIds(
                    addressSchoolList.stream()
                            .map(EduAddressSchool::getAddressSchoolId)
                            .collect(Collectors.toList()));
        }
    }


    @Override
    @OpApi(funcCode = "eduaddress0009", title = "学校学区数据导出", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void exportAddressInfo(SchoolAddressQueryVO vo, HttpServletResponse response) {
        ExcelVO excelVO = new ExcelVO();
        excelVO.setModelCode(vo.getModelCode());
        ExcelModelVO excelModelVO = excelIntegration.getModel(excelVO);

        String destFilePath = this.tempPath + "/" + IdUtil.fastSimpleUUID() + "." + excelModelVO.getExcelType();
        int pageNum = 1;
        setData(excelModelVO, null, destFilePath, vo, pageNum);
        String fileName = vo.getFileName();
        if (StringUtils.isBlank(fileName)) {
            fileName =
                    excelModelVO.getModelName()
                            + "_"
                            + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN)
                            + "."
                            + (StringUtils.isBlank(excelModelVO.getExcelType())
                            ? "xls"
                            : excelModelVO.getExcelType());
        }
        File file = FileUtil.file(destFilePath);
        BufferedInputStream in = null;
        try {
            in = FileUtil.getInputStream(file);
            ServletUtil.write(response, in, "application/octet-stream;charset=utf-8", fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileUtil.del(destFilePath);
        }

    }

    @Override
    @OpApi(funcCode = "eduaddress0010", title = "批量定时设置地址库的行政区划", funcType = FuncTypeEnum.other, publicFlag = BoolEnum.TRUE)
    public void setAreaCode(BaseVO vo) {
        LambdaQueryWrapper<EduAddress> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EduAddress::getStatus, BoolEnum.TRUE.getType())
                .eq(EduAddress::getFictitious, BoolEnum.FALSE.getType())
                .isNotNull(EduAddress::getAddressTreeId)
                .isNull(EduAddress::getAreaCode);
        PageHelper.startPage(1, 1000);
        List<EduAddress> list = eduAddressService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        PageInfo<EduAddress> pageInfo = new PageInfo<>(list);
        for (EduAddress eduAddress : pageInfo.getList()) {
            if (eduAddress.getAddressTreeId() != null) {
                setAreaCode(eduAddress, eduAddress.getAddressTreeId());
                eduAddressService.updateById(eduAddress);
            }
        }
    }

    @Override
    @OpApi(funcCode = "eduaddress0012", title = "修改错误地址状态", funcType = FuncTypeEnum.update)
    @Transactional
    public void markToNoProcessing(EduAddressBatchKeyVO vo) {
        if (ObjectUtils.isEmpty(vo)){
            throw new AppException("请求参数不能为空");
        }
        if (ObjectUtils.isEmpty(SessionUtil.getSessionInfo())){
            throw new AppException("用户登录信息已过期，请查询登录后重试");
        }
        UpdateWrapper<EduAddress> updateWrapper = new UpdateWrapper<>();
        List<String> addressIds = vo.getAddressIds();
        updateWrapper.lambda()
                .in(EduAddress::getAddressId,addressIds)
                .set(EduAddress::getHandleStatus, vo.getHandlesStatus())
                .set(EduAddress::getUpdateTime,new Date())
                .set(EduAddress::getUpdateName,SessionUtil.getSessionInfo().getUserId())
                .set(EduAddress::getHandleTime,new Date());
        eduAddressService.update(updateWrapper);
    }

    @Override
    @OpApi(funcCode = "eduaddress0013", title = "得到账号可以显示的地址信息", funcType = FuncTypeEnum.update)
    public  List<EduAreaInfoVO> getAreaInfo(BaseVO vo) {
        SessionInfo sessionInfo = SessionUtil.getSessionInfo();
        if (ObjectUtils.isEmpty(sessionInfo)){
            throw new AppException("用户登录信息已过期，请查询登录后重试");
        }
        if (ObjectUtils.isEmpty(sessionInfo.getAreaCode())){
            throw new AppException("该账号未绑定行政区划，请先绑定行政区划后重试！");
        }
        //得到本账号的行政区划。
        String areaCode = sessionInfo.getAreaCode();

        if (areaCode.length() > 6){
            throw new AppException("该账号绑定的行政区划不是县及县级以上的，数据有误！");
        }
        QueryWrapper<SysDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysDict::getDictField,"AREA")
                .eq(SysDict::getDictKey,areaCode);
        SysDict areaNode = sysDictService.getOne(queryWrapper);
        //得到地址链路信息
        EduAreaInfoVO rootArea = this.getAreaLinkInfo(areaNode);
        List<EduAreaInfoVO> rootList = Arrays.asList(rootArea);
       return rootList;
    }

    @Override
    @Transactional
    @OpApi(funcCode = "eduaddress0014", title = "处理错误地址", funcType = FuncTypeEnum.update)
    public void updateErrorAddress(EduAddressKeysVO vo) {
        if (CollectionUtils.isEmpty(vo.getAddressIds())) {
            throw new AppException("地址集合不能为空");
        }
        List<String> addressIds = vo.getAddressIds();
        //校验参数表行政区划编码是否为正确的
        EduAddressTreeOriginal areaNode = originalService.getOne(new QueryWrapper<EduAddressTreeOriginal>()
                .lambda().eq(EduAddressTreeOriginal::getAreaCode, vo.getAreaCode()), false);
        if (ObjectUtils.isEmpty(areaNode)) {
            throw new AppException("该行政区划在参数表未配置数据不存在，请检查参数表数据是否正确！");
        }
        EduAddressTreeOriginal parentNode = originalService.getById(areaNode.getParentId());
        List<EduAddress> eduAddresses = eduAddressService.listByIds(addressIds);
        eduAddresses.forEach(item -> {
            if (!HandleStatusEnum.fail.getType().equals(item.getHandleStatus())) {
                throw new AppException("地址状态异常，请稍后再试");
            }
            //1.修改地址信息
            item.setAreaCode(vo.getAreaCode());
            item.setCityCode(parentNode.getAreaCode());
            if (!ObjectUtils.isEmpty(vo.getStreetCode())){
                item.setStreetCode(vo.getStreetCode());
            }
            eduAddressService.updateById(item);
        });
        //遍历格式化地址
//        for (EduAddress eduAddress : eduAddresses) {
//            EduAddressVO eduAddressVO = Convert.convert(EduAddressVO.class, eduAddress);
//            this.parseAddress(eduAddressVO, areaNamePrefix);
//        }
        EduAddressTreeInitialQueryVO queryVO = new EduAddressTreeInitialQueryVO();
        queryVO.setAddressIds(addressIds);
        eduAddressTreeIntegration.addressAfreshParse(queryVO);
    }

    @Override
    public void parseAddressForJob(EduAddressVO eduAddress) {
        try {
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            TransactionStatus status = transactionManager.getTransaction(def);
            try {
                this.parseAddress(eduAddress);
                transactionManager.commit(status);
            } catch (Exception e) {
                transactionManager.rollback(status);
                throw e;
            }
        } catch (Exception e) {
            log.error("地址格式化错误：{}", eduAddress.getAddressName(), e);
            this.updateEduAddress(eduAddress.getAddressId(), null,
                    HandleStatusEnum.fail.getType(), e.getMessage());
        }
    }

    @Override
    @OpApi(funcCode = "eduaddress0015", title = "待审核地址统计", funcType = FuncTypeEnum.query, publicFlag = BoolEnum.TRUE)
    public PageInfo<EduAddressStatisticsVO> toBeReviewedAddressStatistics(EduAddressQueryVO vo) {
        if (StringUtils.isBlank(vo.getAreaCode())){
            vo.setAreaCode(SessionUtil.getAreaCode());
        }
        String areaCode = eduHelper.thisAreaCode();
        if (StringUtils.isNotBlank(vo.getAreaCode()) && areaCode.equals(vo.getAreaCode())) {
            vo.setAreaCode(null);
        }
        if (vo.getPageNum() == null) {
            vo.setPageNum(1);
        }
        if (vo.getPageSize() == null) {
            vo.setPageSize(1000);
        }

        //是否本年本学段的标志
        CommonVO addressParseCheck = new CommonVO();
        addressParseCheck.setParamKey("address_audit_bn_flag");
        addressParseCheck.setAreaCode(vo.getAreaCode());
        String auditBnFlag = commonIntegration.getValueByKey(addressParseCheck);
        if (StringUtils.isEmpty(auditBnFlag)){
            //如果为空或者没有配置，默认查询本年的数据
            auditBnFlag = BoolEnum.TRUE.getType();
        }
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<EduAddressStatisticsVO> list = eduAddressService.toBeReviewedAddressStatistics(vo,auditBnFlag);
        if (CollectionUtils.isEmpty(list)) {
            if (StringUtils.isNotBlank(vo.getSchoolId())) {
                EduSchoolVO schoolVO = schoolService.getDetail(vo.getSchoolId());
                if (!ObjectUtils.isEmpty(schoolVO)) {
                    EduAddressStatisticsVO statisticsVO = new EduAddressStatisticsVO();
                    statisticsVO.setCount(0);
                    statisticsVO.setSchoolId(vo.getSchoolId());
                    statisticsVO.setSchoolName(schoolVO.getSchoolName());
                    statisticsVO.setShortName(schoolVO.getShortName());
                    statisticsVO.setSchoolCategory(schoolVO.getSchoolCategory());
                    list.add(statisticsVO);
                    PageInfo<EduAddressStatisticsVO> pageInfo = new PageInfo<>(list);
                    return PagerUtil.parsePagerVo(list, pageInfo);
                }
            }
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        //for循环从缓存中取学校信息进行设置
        List<EduAddressStatisticsVO> resultList = list.stream().map(item -> {
            EduSchoolVO schoolVO = schoolService.getDetail(item.getSchoolId());
            if (!ObjectUtils.isEmpty(schoolVO)) {
                item.setSchoolName(schoolVO.getSchoolName());
                item.setShortName(schoolVO.getShortName());
                item.setSchoolCategory(schoolVO.getSchoolCategory());
            }
            return item;
        }).collect(Collectors.toList());
        PageInfo<EduAddressStatisticsVO> pageInfo = new PageInfo<>(list);
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    private void parseAddress(EduAddressVO eduAddress) {
        parseAddress(eduAddress, null);
    }

    private void parseAddress(EduAddressVO eduAddress, String prefix) {
        String address = eduAddress.getAddressName();
        if (!StringUtils.isEmpty(prefix)) {
            address = prefix + address;
        }
        AddressRequest addressRequest = new AddressRequest(address, eduAddress.getAddressId());
        AddressVO addressVO = eduAddressTreeIntegration.parseAddressAutoAndSave(addressRequest);
        addressVO.setEduAddressId(eduAddress.getAddressId());
        //更新地址树表中的关联id
        UpdateWrapper<EduAddressTree> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(EduAddressTree::getAddressId, addressVO.getAddressId())
                .set(EduAddressTree::getEduAddressId, eduAddress.getAddressId());
        eduAddressTreeService.update(updateWrapper);
        this.updateEduAddress(eduAddress.getAddressId(), addressVO,
                HandleStatusEnum.success.getType(), "处理成功");
        //调用下游功能
        for (AddressObserver addressObserver : OBSERVER_LIST) {
            try {
                //如果有传入前缀，需要将原始地址重置
                if (!StringUtils.isEmpty(prefix)) {
                    addressVO.setOriginAdd(eduAddress.getAddressName());
                }
                addressObserver.invoke(addressVO);
            } catch (Exception e) {
                log.error("调用下游功能失败，地址：{}", eduAddress.getAddressName(), e);
            }
        }
    }


    private void updateEduAddress(String addressId, AddressVO addressVO, String handleStatus, String handleMessage) {
        try {
            if (handleMessage.length() > 500) {
                handleMessage = handleMessage.substring(0, 500);
            }
            UpdateWrapper<EduAddress> updateWrapper = new UpdateWrapper<>();
            updateWrapper.lambda().set(EduAddress::getHandleStatus, handleStatus)
                    .set(EduAddress::getHandleMessage, handleMessage)
                    .set(EduAddress::getHandleTime, new Date())
                    .eq(EduAddress::getAddressId, addressId);
            if (HandleStatusEnum.success.getType().equals(handleStatus)) {
                String parentPath = AddressUtil.getParentPath(addressVO);
                updateWrapper.lambda().set(EduAddress::getParentPath, parentPath)
                        .set(EduAddress::getAddressTreeId, addressVO.getAddressId());
                if(StringUtils.isNotBlank(addressVO.getCityCode())){
                    //地址表中设置所属城市
                    updateWrapper.lambda().set(EduAddress::getCityCode, addressVO.getCityCode());
                }
                if(StringUtils.isNotBlank(addressVO.getDistrictCode())){
                    //地址表中设置所属区县
                    updateWrapper.lambda().set(EduAddress::getAreaCode, addressVO.getDistrictCode());
                }
                if(StringUtils.isNotBlank(addressVO.getTownCode())){
                    //地址表中设置所属街道
                    updateWrapper.lambda().set(EduAddress::getStreetCode, addressVO.getTownCode());
                }
            }
            boolean update = eduAddressService.update(updateWrapper);
            if (!update) {
                throw new AppException("更新edu_address失败，update返回false");
            }
        } catch (Exception e) {
            log.error("更新edu_address异常，address_id:{},handleStatus:{},handleMessage:{}",
                    addressId, handleStatus, handleMessage, e);
        }
    }


    /**
     * 传入字典中的数据，从字典表找出链路信息
     * @param areaNode
     */
    private   EduAreaInfoVO getAreaLinkInfo(SysDict areaNode) {
        EduAreaInfoVO rootAreaInfoVO = new EduAreaInfoVO();
        BeanUtils.copyProperties(areaNode,rootAreaInfoVO);
        QueryWrapper<SysDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysDict::getDictField,"AREA")
                .eq(SysDict::getParentKey,areaNode.getDictKey());
        List<SysDict> list = sysDictService.list(queryWrapper);
        if (!ObjectUtils.isEmpty(list)){
            //如果list 不为null，还有子节点数据。可能是省，市数据
            List<EduAreaInfoVO> EduAreaInfoVOList = list.stream().map(item -> {
                //定义变量，进行转换 item
                EduAreaInfoVO eduAreaInfoVO = new EduAreaInfoVO();
                BeanUtils.copyProperties(item,eduAreaInfoVO);
                QueryWrapper<SysDict> wrapper = new QueryWrapper<>();
                wrapper.lambda()
                        .eq(SysDict::getDictField, "AREA")
                        .eq(SysDict::getParentKey, item.getDictKey());
                //遍历每个节点，得到子节点
                List<SysDict> childNode = sysDictService.list(wrapper);

                //判断childNode是否为Null
                if (!ObjectUtils.isEmpty(childNode)) {
                    //如果不为null  说明areaNode是省级数据  item是市级数据   childNode就是item下的子级节点
                    //将子级节点转换 设置进areaNodeChild中
                    List<EduAreaInfoVO> childList = Convert.toList(EduAreaInfoVO.class, childNode);
                    eduAreaInfoVO.setAreaNodeChild(childList);
                }
                //将list ，转换为 EduAreaInfoVOList
                return eduAreaInfoVO;
            }).collect(Collectors.toList());
            rootAreaInfoVO.setAreaNodeChild(EduAreaInfoVOList);
        }
        return rootAreaInfoVO;
    }


    private void setAreaCode(EduAddress eduAddress, Long addressId) {
        if (addressId != null) {
            EduAddressTree eduAddressTree = eduAddressTreeService.getById(addressId);
            if (eduAddressTree == null) {
                return;
            }
            if ("city".equalsIgnoreCase(eduAddressTree.getAreaType())) {
                eduAddress.setCityCode(eduAddressTree.getAreaCode());
            } else if ("district".equalsIgnoreCase(eduAddressTree.getAreaType())) {
                eduAddress.setAreaCode(eduAddressTree.getAreaCode());
                if (eduAddressTree.getParentId() != null) {
                    setAreaCode(eduAddress, eduAddressTree.getParentId());
                }
            } else if ("town".equalsIgnoreCase(eduAddressTree.getAreaType())) {
                eduAddress.setStreetCode(eduAddressTree.getAreaCode());
                if (eduAddressTree.getParentId() != null) {
                    setAreaCode(eduAddress, eduAddressTree.getParentId());
                }
            } else {
                if (eduAddressTree.getParentId() != null) {
                    setAreaCode(eduAddress, eduAddressTree.getParentId());
                }
            }
        }
    }

    private void setData(ExcelModelVO excelModelVO, ExcelWriter excelWriter, String destFilePath, SchoolAddressQueryVO vo, int pageNum) {
        vo.setPageNum(pageNum);
        vo.setPageSize(500);
        boolean closeFlag = false;
        try {
            PageInfo<EduAddressVO> pageInfo = getParentAdderssList(vo);
            String total = String.valueOf(pageInfo.getTotal());
            List<Object> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(pageInfo.getList())) {
                for (EduAddressVO eduAddressVO : pageInfo.getList()) {
                    list.add(eduAddressVO);
                }
            }
            if (pageNum == 1) {
                if (excelWriter == null) {
                    excelWriter = excelCommonHelper.createExcelWriter(excelModelVO, destFilePath, Integer.parseInt(total));
                }
                excelCommonHelper.writeBean(excelWriter, list);
            } else {
                excelCommonHelper.writeBean(excelWriter, list);
            }
            if (pageInfo.isHasNextPage()) {
                pageNum = pageNum + 1;
                setData(excelModelVO, excelWriter, destFilePath, vo, pageNum);
            } else {
                closeFlag = true;
            }
        } catch (AppException appEx) {
            throw appEx;
        } catch (Exception e) {
            throw new AppException("调用自定义写入服务异常:" + e.getMessage());
        } finally {
            if (closeFlag && excelWriter != null) {
                excelWriter.close();
            }
        }
    }


}
